package com.nars.networking;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class E1 {

	private static BufferedReader bufferedReader(Socket socket)
			throws IOException {
		InputStreamReader isr = new InputStreamReader(socket.getInputStream());
		return new BufferedReader(isr);
	}

	private static BufferedWriter bufferedWriter(Socket socket)
			throws IOException {
		OutputStreamWriter isr = new OutputStreamWriter(
				socket.getOutputStream());
		return new BufferedWriter(isr);
	}

	private static void write(Socket socket, String message) throws IOException {
		BufferedWriter bw = bufferedWriter(socket);
		bw.write(message);
		// DO NOT close but just flush since close will close also the socket
		bw.flush();
	}

	static class Client extends Thread {

		private Socket socket;
		private Map<String, Client> map;
		private String username;

		// TODO timeout... if
		public Client(Socket socket, Map<String, Client> map)
				throws IOException {
			this.socket = socket;
			this.map = map;
		}

		@Override
		public void run() {
			if (username == null) {
				register();
			} else {
				welcome();

			}			
		}	

		private void welcome() {
			try {
				write(socket, "OK. Enter operation\n");
				BufferedReader br = bufferedReader(socket);
				String line = br.readLine();
				Pattern pattern = Pattern.compile("(\\w+)\\s+(\\w+)");
				Matcher matcher = pattern.matcher(line);
				if (matcher.find()) {
					// String command = matcher.group(1);
					String command = matcher.group();					
					write(socket, "OK. You have entered " + command + ".\n");
					socket.setSoTimeout(1000);
				} else {
					BufferedWriter bw = bufferedWriter(socket);
					bw.write("ERROR. Try again.\n");
					bw.close();
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		private void register() {
			try {
				write(socket, "OK. Welcome, please register.\n");
				BufferedReader br = bufferedReader(socket);
				String line = br.readLine();
				Pattern pattern = Pattern.compile("(\\w+)\\s+(\\w+)");
				Matcher matcher = pattern.matcher(line);
				if (matcher.find()) {
					// String command = matcher.group(1);
					String username = matcher.group();
					this.username = username;
					map.put(username, this);
					write(socket, "OK. User " + username + " registered.\n");
					socket.setSoTimeout(1000);
				} else {
					BufferedWriter bw = bufferedWriter(socket);
					bw.write("ERROR. Try again.\n");
					bw.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * @param args
	 * @throws IOException
	 */
	public static void main(String[] args) throws IOException {
		Map<String, Client> map = new HashMap<String, Client>();
		ServerSocket ss = new ServerSocket(2222);
		while (true) {
			Socket s = ss.accept();
			Client client = new Client(s, map);
			client.start();
			// map.put(client.username, client);
		}
	}
}
